#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QClipboard>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QProcess>
#include <QTextStream>

bool fileExists(QString path) {
    QFileInfo check_file(path);
    return (check_file.exists() && check_file.isFile());
}

bool urlExists(QString url_string)
{
    QUrl url(url_string);
    QTcpSocket socket;
    socket.connectToHost(url.host(), 80);
    if (socket.waitForConnected())
    {
        socket.write("HEAD " + url.path().toUtf8() + " HTTP/1.1\r\n"
                                                     "Host: " + url.host().toUtf8() + "\r\n\r\n");
        if (socket.waitForReadyRead())
        {
            QByteArray bytes = socket.readAll();
            if (bytes.contains("https://link.educom.ru/api/school/items"))
            {
                return true;
            }
        }
    }
    return false;
}

QString runproc(QString cmds)
{
    QProcess process;
    QString temp;
    process.start("bash", QStringList() << "-c" << cmds);
    if(process.waitForStarted() and process.waitForFinished())
        temp = QString(process.readAllStandardOutput()).trimmed();
    return temp;
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Обработка нажатия Enter в поле поиска
    connect(ui->schoolfilter, SIGNAL(returnPressed()), SLOT(on_searchButton_clicked()));

    // Модели для таблицы школ и таблицы зданий
    schoolsmodel = new QStandardItemModel(this);
    buildingsmodel = new QStandardItemModel(this);

    // Привязка моделей к таблицам
    ui->schooltable->setModel(schoolsmodel);
    ui->buildingstable->setModel(buildingsmodel);
    school_model_settings();

    //Скрываем таблицы поиска
    ui->searchPanel->hide();

    // таймер статуса UDS
    udsTimer = new QTimer();
    udsTimer->setInterval(100000);
    connect(udsTimer, SIGNAL(timeout()), this, SLOT(checkUDS()));
    udsTimer->start();

    // Иконка в трее
    m_trayIcon = new QSystemTrayIcon( this );
    //m_trayIcon->setToolTip("Информация об устройстве");
    connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(show()));
    // Установка цвета иконки в зависимости от наличия файлов
    checkUDS();

    // Создание пунктов меню для иконки в трее
    QMenu * menu = new QMenu(this);
    QAction * helpMessage = new QAction("Информация", this);
    QAction * viewWindow = new QAction("Развернуть окно", this);
    QAction * quitAction = new QAction("Выход", this);

    // подключаем сигналы нажатий на пункты меню к соответсвующим слотам.
    // Первый пункт меню показывает справочную информацию
    // следующий разворачивает приложение из трея,
    // следующий пункт меню завершает приложение
    connect(helpMessage, SIGNAL(triggered()), this, SLOT(on_showHelp_triggered()));
    connect(viewWindow, SIGNAL(triggered()), this, SLOT(show()));
    connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));

    menu->addAction(helpMessage);
    menu->addAction(viewWindow);
    menu->addAction(quitAction);

    // Устанавливаем контекстное меню на иконку
    // и показываем иконку приложения в трее
    m_trayIcon->setContextMenu(menu);
    m_trayIcon->show();

    // Настраиваем поле ввода имени компьютера и дополнительные поля
    ui->computername->setText(runproc("hostname"));
    sughostname = "";
    QRegExp rx("[0-9a-zA-Z]{1,5}");
    ui->schoolname->setValidator(new QRegExpValidator(rx, this));
    ui->corpname->setValidator(new QRegExpValidator(rx, this));
    ui->cabname->setValidator(new QRegExpValidator(rx, this));
    rx.setPattern("[0-9a-zA-Z]{1,8}");
    ui->devicename->setValidator(new QRegExpValidator(rx, this));
    rx.setPattern("([a-zA-Z]+[_0-9a-zA-Z\\-]*\\.{0,1})+");
    ui->computername->setValidator(new QRegExpValidator(rx, this));

    QString trq = "";
    for(int i = 0; i < rq.length(); i++) if(i != 3 && i != 67) trq = rq[i] + trq;
    rq = trq + "=";
    //Предзаполнение данных
    if(runproc("grep ^DE=mos-p$ /var/lib/rosa-iso-info") == "DE=mos-p")
        ui->TypeCombobox->setCurrentIndex(5);
    if (fileExists("/etc/mosinv"))
    {
        sid = runproc("cat /etc/mosinv | head -n1 | tail -n1"); //Не отображаем
        sekis = runproc("cat /etc/mosinv | head -n2 | tail -n1");

        invn = runproc("cat /etc/mosinv | head -n3 | tail -n1");
        ui->InvEdit->setText(invn);
        room = runproc("cat /etc/mosinv | head -n4 | tail -n1");
        ui->RoomEdit->setText(room);
        dtype = runproc("cat /etc/mosinv | head -n5 | tail -n1");
        ui->TypeCombobox->setCurrentIndex(dtype.toInt());
        drole = runproc("cat /etc/mosinv | head -n6 | tail -n1");
        ui->RoleCombobox->setCurrentIndex(drole.toInt());
        sfullname  = runproc("cat /etc/mosinv | head -n7 | tail -n1");
        ui->SchoolEdit->setText(sfullname);
        sfulladdr  = runproc("cat /etc/mosinv | head -n8 | tail -n1");
        ui->AddressEdit->setText(sfulladdr);

        ui->schoolfilter->setText("");
        ui->applyButton->setEnabled(true);
    }
    else
    {
        // Таймер идентификации устройства
        identifyTimer = new QTimer();
        identifyTimer->setInterval(1000000);
        connect(identifyTimer, SIGNAL(timeout()), this, SLOT(showIdentificationMessage()));
        identifyTimer->start();
    }
}

MainWindow::~MainWindow()
{
    delete ui;
    delete schoolsmodel;
}

void MainWindow::on_searchButton_clicked()
{
    if(urlExists("https://link.educom.ru/api/school/items"))
    {
        if(ui->TypeCombobox->currentIndex() > -1 && ui->RoleCombobox->currentIndex() > -1)
        {
            ui->searchPanel->show();
            if(checkbase)
            {
                checkbase = false;
                QUrl myurl;
                QUrlQuery myurlquery;
                QNetworkRequest request;
                QNetworkAccessManager *restclient;
                myurl.setScheme("https");
                myurl.setHost("link.educom.ru");
                myurl.setPath("/api/school/items");
                myurlquery.addQueryItem("per_page", "9000");
                myurl.setQuery(myurlquery.query());
                request.setRawHeader("Authorization", QByteArray::fromBase64(rq.toUtf8()));
                request.setRawHeader("Accept", "application/json");
                request.setRawHeader("Content-Type", "application/json");
                request.setUrl(myurl);
                restclient = new QNetworkAccessManager(this);
                connect(restclient, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyschoolist(QNetworkReply*)));
                restclient->get(request);
            }
            else
            {
                QString squery = ui->schoolfilter->text().toLower();
                TSchool srec;
                schoolsmodel->clear();
                school_model_settings();
                for(int i = 0; i < dbSch.count(); i++)
                {
                    srec = dbSch.value(i);
                    if(srec.name.toLower().indexOf(squery) >= 0)
                    {
                        QList<QStandardItem *> standardItemsList;
                        standardItemsList.append(new QStandardItem(srec.name));
                        standardItemsList.append(new QStandardItem(srec.id));
                        standardItemsList.append(new QStandardItem(srec.ekis));
                        schoolsmodel->insertRow(schoolsmodel->rowCount(), standardItemsList);
                    }
                }
                schoolsmodel->sort(0);
                ui->schooltable->resizeColumnsToContents();
            }
        }
        else
        {
            QMessageBox::warning(this, "Ошибка!","Не заданы назначение и тип устройства!");
        }
    }
    else
    {
        QMessageBox::warning(this, "Внимание","API недоступно.\nПроверьте подключение к сети интернет.");
    }
}

void MainWindow::school_model_settings()
{
    // https://russianblogs.com/article/1801707717/
    // Заголовок
    ui->schooltable->setSortingEnabled(true);
    schoolsmodel->setColumnCount(3);
    QStringList labels = QString("Школа").simplified().split(",");
    schoolsmodel->setHorizontalHeaderLabels(labels);
    ui->schooltable->setColumnHidden(1, true);
    ui->schooltable->setColumnHidden(2, true);
    ui->schooltable->resizeColumnsToContents();

    ui->buildingstable->setSortingEnabled(true);
    buildingsmodel->setColumnCount(2);
    labels = QString("Здание").simplified().split(",");
    buildingsmodel->setHorizontalHeaderLabels(labels);
    ui->buildingstable->setColumnHidden(1, true);
    ui->buildingstable->resizeColumnsToContents();

}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(this->isVisible())
    {
        event->ignore();
        this->hide();
        m_trayIcon->showMessage("Идентификация",
                                "Приложение свернуто в трей. Для того чтобы "
                                "развернуть окно приложения, щёлкните по иконке приложения в трее");
    }
    else
        exit(0);
}


void MainWindow::on_schooltable_clicked(const QModelIndex &index)
{
    if(urlExists("https://link.educom.ru/api/school/items"))
    {
        schoolid = schoolsmodel->data(schoolsmodel->index(ui->schooltable->currentIndex().row(),1)).toString();
        sekis = schoolsmodel->data(schoolsmodel->index(ui->schooltable->currentIndex().row(),2)).toString();
        sfullname = schoolsmodel->data(schoolsmodel->index(ui->schooltable->currentIndex().row(),0)).toString();

        QUrl myurl;
        QUrlQuery myurlquery;
        QNetworkRequest request;
        QNetworkAccessManager *restclient;
        myurl.setScheme("https");
        myurl.setHost("link.educom.ru");
        myurl.setPath("/api/school/items/" + schoolid);
        request.setUrl(myurl);
        request.setRawHeader("Authorization", QByteArray::fromBase64(rq.toUtf8()));
        request.setRawHeader("Accept", "application/json");
        request.setRawHeader("Content-Type", "application/json");
        restclient = new QNetworkAccessManager(this);
        connect(restclient, SIGNAL(finished(QNetworkReply*)), this, SLOT(replybuildingslist(QNetworkReply*)));
        restclient->get(request);
    }
    else
    {
        QMessageBox::warning(this, "Внимание","API недоступно.\nПроверьте подключение к сети интернет.");
    }
}


void MainWindow::on_applyButton_clicked()
{
    if(ui->TypeCombobox->currentIndex() > -1 && ui->RoleCombobox->currentIndex() > -1)
    {
        readVariablesFromUI();
        const QString FILE_NAME = runproc("mktemp");
        QFile out( FILE_NAME );
        if( out.open( QIODevice::WriteOnly ) )
        {
            QTextStream stream( &out );
            stream << sid << "\n" << sekis << "\n" << invn << "\n" << room << "\n" << dtype << "\n" << drole << "\n" << sfullname << "\n" << sfulladdr;
            out.close();
        }
        QProcess process;
        QString temp;
        process.start("pkexec", QStringList() << "bash" << "-c" << "cat " + FILE_NAME + " > /etc/mosinv");
        if(process.waitForStarted() and process.waitForFinished())
            temp = QString(process.readAllStandardOutput()).trimmed();
        if(process.exitCode()) QMessageBox::warning(this, "Ошибка!","Возникла проблема при выполнении команды!<br>Попробуйте повторить.");
        out.remove();
        ui->searchPanel->hide();
    }
    else
    {
        QMessageBox::warning(this, "Ошибка!","Не заданы назначение и тип устройства!");
    }
}

void MainWindow::replyschoolist(QNetworkReply *reply)
{
    QByteArray bytes = reply->readAll();
    QString str = QString::fromUtf8(bytes.data(), bytes.size());

    // Вывод в лог кода статуса ответа
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qWarning() << QVariant(statusCode).toString();

    TSchool schrec;
    dbSch.clear();

    QJsonDocument jsdoc = QJsonDocument::fromJson(bytes);
    if(!jsdoc.isNull())
    {
        QJsonObject jsobj = jsdoc.object();
        QJsonValue jv = jsobj.value("data");
        QJsonArray ja = jv.toArray();

        for(int i = 0; i < ja.count(); i++)
        {
            QJsonObject school = ja.at(i).toObject();
            schrec.id = school.value("id").toVariant().toString();
            schrec.ekis = school.value("ekis_id").toVariant().toString();
            schrec.name = school.value("name").toString();
            dbSch << schrec;
        }
        reply->deleteLater();
        on_searchButton_clicked();
    }
}

void MainWindow::replybuildingslist(QNetworkReply *reply)
{
    QByteArray bytes = reply->readAll();
    QString str = QString::fromUtf8(bytes.data(), bytes.size());

    // Вывод в лог кода статуса ответа
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qWarning() << QVariant(statusCode).toString();

    TSchoolAddres srec;
    dbSchools.clear();

    QJsonDocument jsdoc = QJsonDocument::fromJson(bytes);
    QJsonObject jsobj = jsdoc.object();
    QJsonObject dataobj = jsobj.value("data").toObject();
    QJsonValue jv = dataobj.value("buildings");
    QJsonArray ja = jv.toArray();

    buildingsmodel->clear();
    school_model_settings();
    for(int i = 0; i < ja.count(); i++)
    {
        QJsonObject school = ja.at(i).toObject();
        srec.id = school.value("id").toVariant().toString();
        srec.address = school.value("addr").toString();
        dbSchools << srec;
        QList<QStandardItem *> standardItemsList;
        standardItemsList.append(new QStandardItem(srec.address));
        standardItemsList.append(new QStandardItem(srec.id));
        buildingsmodel->insertRow(buildingsmodel->rowCount(), standardItemsList);
    }
    buildingsmodel->sort(0);
    ui->buildingstable->resizeColumnsToContents();
    reply->deleteLater();
}

void MainWindow::on_buildingstable_clicked(const QModelIndex &index)
{
    sfulladdr = buildingsmodel->data(buildingsmodel->index(ui->buildingstable->currentIndex().row(),0)).toString();
    sid = buildingsmodel->data(buildingsmodel->index(ui->buildingstable->currentIndex().row(),1)).toString();

    readVariablesFromUI();

    ui->SchoolEdit->setText(sfullname);
    ui->AddressEdit->setText(sfulladdr);

    ui->applyButton->setEnabled(true);
}

void MainWindow::on_actionGeneration_hostname_triggered()
{
    ui->sugname->setText(genhostname());
}

void MainWindow::showIdentificationMessage()
{
    if (!fileExists("/etc/mosinv"))
    {
        m_trayIcon->showMessage("Устройство не идентифицировано!",
                                "Обратитесь к техническому специалисту для завершения процесса идентификации устройства");
    }
    else
    {
        identifyTimer->stop();
        checkUDS();
    }
}

QString MainWindow::genhostname()
{
    sughostname = "";
    readVariablesFromUI();
    if(drole=="2") sughostname = sughostname + "s";
    if(dtype=="1") sughostname = sughostname + "c";
    if(dtype=="2") sughostname = sughostname + "m";
    if(dtype=="3") sughostname = sughostname + "n";
    if(dtype=="4") sughostname = sughostname + "t";
    if(dtype=="5") sughostname = sughostname + "p";
    if(ui->schoolname->text() != "")
    {
        sughostname = sughostname + ui->schoolname->text();
        if(ui->corpname->text() != "")
        {
            sughostname = sughostname + "-" + ui->corpname->text();
            if(ui->cabname->text() != "") sughostname = sughostname + "-" + ui->cabname->text();
        }
        if(ui->devicename->text() != "") sughostname = sughostname + "-" + ui->devicename->text();
    }
    return sughostname;
}

void MainWindow::on_chNameandRestart_clicked()
{
    QProcess process;
    QString temp, execommand;
    execommand = "hostnamectl hostname " + ui->computername->text() + " && reboot";
    if(ui->machineid->isChecked())
        execommand = "rm -f /etc/machine-id && rm -f /var/lib/dbus/machine-id && dbus-uuidgen --ensure && systemd-machine-id-setup && " + execommand;
    process.start("pkexec", QStringList() << "bash" << "-c" << execommand);
    if(process.waitForStarted() and process.waitForFinished())
        temp = QString(process.readAllStandardOutput()).trimmed();
    if(process.exitCode()) QMessageBox::warning(this, "Ошибка!","Возникла проблема при выполнении команды!<br>Попробуйте повторить.");
}


void MainWindow::on_sugnameButton_clicked()
{
    ui->computername->setText(ui->sugname->text());
}

void MainWindow::checkUDS()
{
    // Настройка иконки трея
    bool regUDS = fileExists("/etc/uds-system-agent/registration");
    bool linkAddress = fileExists("/etc/uds-system-agent/binding");
    bool invSchool = fileExists("/etc/mosinv");

    if (regUDS && linkAddress && invSchool)
    {
        appicon = ":/img/mos-identify.svg";
        statusMessage = "Информация об устройстве";
        udsTimer->stop();
    }
    else if (regUDS && linkAddress)
    {
        appicon = ":/img/greencircle.svg";
        statusMessage = "Внесите данные в форму";
    }
    else if (regUDS)
    {
        appicon = ":/img/yellowcircle.svg";
        statusMessage = "Не определён адрес здания";
    }
    else
    {
        appicon = ":/img/redcircle.svg";
        statusMessage = "Нет регистрации устройства через интернет";
    }

    // Вывод UDS ID
    if (regUDS)
        ui->UDSID->setText(runproc("cat /etc/uds-system-agent/registration"));

    m_trayIcon->setToolTip(statusMessage);
    setWindowTitle(statusMessage);
    m_trayIcon->setIcon(QIcon(QPixmap(appicon)));
}


void MainWindow::on_RoleCombobox_currentIndexChanged(int index)
{
    ui->TypeCombobox->setEnabled(index != 3);
    if(index != 3 && ui->TypeCombobox->currentIndex() == 5) ui->TypeCombobox->setCurrentIndex(-1);
    if(index == 3) ui->TypeCombobox->setCurrentIndex(5);
}

void MainWindow::readVariablesFromUI()
{
    invn = ui->InvEdit->text();
    room = ui->RoomEdit->text();
    drole = QString::number(ui->RoleCombobox->currentIndex());
    if(drole == 3)
    {
        dtype = 5;
        ui->TypeCombobox->setCurrentIndex(5);
    }
    else
        dtype = QString::number(ui->TypeCombobox->currentIndex());
}


void MainWindow::on_TypeCombobox_currentIndexChanged(int index)
{
    if(index == 5) ui->RoleCombobox->setCurrentIndex(3);
}


void MainWindow::on_cpUDSID_clicked()
{
    QClipboard *clipboard = QGuiApplication::clipboard();
    clipboard->setText(ui->UDSID->text());
}

void MainWindow::on_showHelp_triggered()
{
    QStringList helpmessage={"<h3>Цвет индикатора на панели задач</h3>",
                             "<p><h4>Красный круг</h4>"
                             "<ul><li>Ошибка регистрации в системе дистрибуции.</li></ul>"
                             "<i>Проверьте соединение с сетью интернет и доступу к порталу school.mos.ru</i></p>",
                             "<p><h4>Жёлтый круг</h4>"
                             "<ul><li>Устройство зарегистрировано в системе дистрибуции.</li>"
                             "<li>Ошибка идентификации адреса корпуса образовательной организации.</li></ul>"
                             "<i>Для успешной идентификации адреса необходимо подключиться к сети КМС."
                             "(например через Wi-Fi сеть StudyMOS или через проводное соединение,"
                             "проходящее через инфраструктуру МЭШ)</i></p>",
                             "<p><h4>Зелёный круг</h4>"
                             "<ul><li>Устройство зарегистрировано в системе дистрибуции.</li>"
                             "<li>Успешная идентификация адреса корпуса образовательной организации.</li>"
                             "<li>Заполните карточку устройства кликнув на зеленый круг в панели задач:</li>"
                             "<ul>"
                             "<li>инвентарный номер,</li>"
                             "<li>информация о владельце,</li>"
                             "<li>назначение устройства,</li>"
                             "<li>тип устройства,</li>"
                             "<li>образовательную организацию и адрес.</li>"
                             "</ul></ul>"
                             "<i>Для успешной идентификации адреса необходимо подключиться к сети КМС."
                             "(например через Wi-Fi сеть StudyMOS или через проводное соединение,"
                             "проходящее через инфраструктуру МЭШ)</i></p>",
                             "<p><h4>Иконка планшета с карандашом</h4>"
                             "<ul><li>Устройство зарегистрировано в системе дистрибуции.</li>"
                             "<li>Успешная идентификация адреса корпуса образовательной организации.</li>"
                             "<li>Анкета с информацией об устройстве заполнена.</li></ul></p>"};

    QDialog info_dialog;
    info_dialog.setMinimumWidth(800);

    QGridLayout* mainGrid = new QGridLayout;
    mainGrid->setColumnMinimumWidth(1, 700);
    QStringList fnames = {":/img/redcircle.svg", ":/img/yellowcircle.svg", ":/img/greencircle.svg", ":/img/mos-identify.svg"};
    mainGrid->addWidget(new QLabel(helpmessage[0]), 0, 0, 1, 2);
    for(int i = 0; i < fnames.length(); i++){
        QImage* image1 = new QImage(fnames[i]);
        QLabel* image1label = new QLabel;
        image1label->setWordWrap(true);
        *image1 = image1->scaled(QSize(30, 30), Qt::KeepAspectRatio);
        image1label->setPixmap(QPixmap::fromImage(*image1));
        image1label->setAlignment(Qt::AlignLeft);
        mainGrid->addWidget(image1label, i + 1, 0);
        QLabel *textlabel = new QLabel(helpmessage[i + 1]);
        textlabel->setWordWrap(true);
        mainGrid->addWidget(textlabel, i + 1, 1);

    }
    QPushButton* okbutton = new QPushButton("OK");
    connect(okbutton, &QPushButton::clicked, &info_dialog, &QWidget::close);
    mainGrid->addWidget(okbutton, fnames.length() + 1, 0, 1, 2);
    info_dialog.setLayout(mainGrid);
    //    info_dialog.adjustSize();
    info_dialog.exec();
}

